package com.dfs.parent.gateway.config;

import com.dfs.parent.gateway.loadbalancer.GrayInstanceSupplier;
import com.dfs.parent.gateway.props.GrayProperties;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GrayGatewayLoadBalancerConfig {
    @Bean
    public ServiceInstanceListSupplier grayCompatibilitySupplier(
            ConfigurableApplicationContext context, GrayProperties grayProperties) {
        // 注意：2021.x版本的builder用法差异
        ServiceInstanceListSupplier delegate = ServiceInstanceListSupplier.builder()
                .withDiscoveryClient() // 2021.x需明确指定 withBlockingDiscoveryClient 这个是阻塞的
                .withCaching()
                .build(context);
        return new GrayInstanceSupplier(delegate,grayProperties);
    }
}

/**
 * 关键点
 * (1) ServiceInstanceListSupplier.builder()
 * 这是 Spring Cloud LoadBalancer 提供的建造者模式 API，用于构造 ServiceInstanceListSupplier。
 * 主要配置项：
 * .withDiscoveryClient()
 * 使用 DiscoveryClient（如 Eureka、Nacos、Consul）从注册中心获取服务实例列表。
 * .withCaching()
 * 启用缓存，避免每次请求都去注册中心查询，提升性能。
 * (2) ConfigurableApplicationContext context
 * 作用：
 * 传入 Spring 的应用上下文，用于：
 * 访问 Spring 容器中的其他 Bean（如 DiscoveryClient）。
 * 让 ServiceInstanceListSupplier 能够与 Spring 环境集成（如读取配置）。
 * 为什么需要它？
 * build(context) 方法内部会从 context 中获取必要的依赖（如 DiscoveryClient），并初始化 ServiceInstanceListSupplier。
 * (3) GrayInstanceSupplier(delegate)
 * 这是一个自定义的 ServiceInstanceListSupplier，通常用于实现基于版本号的服务实例过滤（如灰度发布）。
 * 装饰器模式（Decorator Pattern）：
 *
 * 它包装了原始的 delegate，可以在返回服务实例列表前进行额外处理（如按版本号过滤）。
 * 2. 完整流程
 * Spring 启动时：
 * 调用 serviceInstanceListSupplier(context) 方法创建 Bean。
 * ServiceInstanceListSupplier.builder().build(context) 会：
 * 从 context 中获取 DiscoveryClient（如 EurekaClient）。
 * 初始化一个带缓存的基础 ServiceInstanceListSupplier。
 * 包装自定义逻辑：
 * 用 GrayInstanceSupplier 包装 delegate，使其具备版本过滤能力。
 * 负载均衡时：
 * Spring Cloud LoadBalancer 调用 GrayInstanceSupplier.get()，返回符合条件的服务实例列表（如仅 dfs-gray 的实例）。
 * 3. 关键问题解答
 * Q1: 为什么需要 ConfigurableApplicationContext？
 * ServiceInstanceListSupplier 的构建依赖 Spring 环境，例如：
 * 获取 DiscoveryClient（如 EurekaDiscoveryClient）。
 * 读取配置（如 spring.cloud.loadbalancer.cache.enabled）。
 * 如果直接 new 一个 ServiceInstanceListSupplier，它无法自动集成 Spring 的依赖注入和配置管理。
 * Q2: withDiscoveryClient() 和 withBlockingDiscoveryClient() 的区别？
 * 方法	使用场景	底层客户端
 * withDiscoveryClient()	响应式编程（如 WebFlux）	ReactiveDiscoveryClient
 * withBlockingDiscoveryClient()	传统 Servlet 阻塞式	DiscoveryClient（如 EurekaClient）
 * Q3: withCaching() 的作用？
 * 避免每次请求都查询注册中心，缓存服务实例列表，提升性能。
 *
 * 缓存时间可通过配置调整：
 *
 * yaml
 * spring:
 *   cloud:
 *     loadbalancer:
 *       cache:
 *         ttl: 5s  # 缓存有效期（默认 35s）
 *         即使你不配置 spring.cloud.loadbalancer.cache.ttl，withCaching() 仍然会启用缓存，并使用 默认的缓存时间（35秒）。
 *1. 推荐配置范围
 * 场景	推荐 TTL	适用情况
 * 高稳定性服务（实例变化少）	30s - 60s	服务实例极少变动（如传统微服务）
 * 中等动态性服务（适度扩缩容）	10s - 30s	大部分生产环境（如 Kubernetes + HPA）
 * 高频动态服务（快速扩缩容/自动弹性）	3s - 10s	Serverless、FaaS 或频繁发布场景
 * 极端敏感场景（需实时发现）	1s - 3s（慎用）	金融交易、实时计费等关键业务
 * 2. 核心考量因素
 * (1) 服务实例变更频率
 * 实例变化快（如 Kubernetes Pod 频繁重启）：TTL 建议 ≤10s
 * （避免请求被路由到已终止的实例）
 * 实例稳定（如 VM 静态部署）：TTL 可放宽至 30s-60s
 * (2) 注册中心性能
 * Eureka/Nacos/Zookeeper：建议 ≥10s（避免高频查询压垮注册中心）
 * 高性能注册中心（如 Consul、ETCD）：可缩至 5s-15s
 * (3) 业务容忍度
 * 可容忍短暂延迟（如商品查询）：TTL 可适当调大（20s-30s）
 * 强一致性要求（如支付交易）：TTL 需缩短（≤5s）
 * 3. 生产环境最佳实践
 * (1) 通用配置（推荐）
 * yaml
 * spring:
 *   cloud:
 *     loadbalancer:
 *       cache:
 *         ttl: 15s  # 平衡实时性与性能的折中选择
 *         capacity: 1024  # 提高缓存容量（防高频服务 OOM）
 *4. 错误配置的后果
 * 配置问题	风险
 * TTL 过长（如 5分钟）	服务下线后仍被路由，导致请求失败
 * TTL 过短（如 1s）	注册中心 QPS 暴增，可能触发限流
 * 未设置缓存容量	高频服务可能导致内存溢出（OOM）
 *总结
 * 大部分生产环境：10s-30s 是安全范围（推荐从 15s 开始调优）。
 * 动态环境（如 K8s）：建议 5s-15s。
 * 关键点：
 * 永远不要禁用缓存（即使设 TTL=1s 也比 cache.enabled=false 安全）。
 *
 * 创建一个支持版本号过滤的 ServiceInstanceListSupplier，用于 Spring Cloud LoadBalancer 的负载均衡。
 * 关键组件：
 * ServiceInstanceListSupplier.builder()：构造基础实例。
 * ConfigurableApplicationContext：提供 Spring 环境集成。
 * VersionServiceInstanceListSupplier：自定义逻辑（如版本过滤）。
 */
